package org.springframework.boot.netty.argumentResolver;

import org.springframework.boot.netty.annotation.PathVariable;
import org.springframework.boot.netty.exception.ConvertException;
import org.springframework.boot.netty.listener.Message;
import org.springframework.boot.netty.support.PathMatchWrapper;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.util.Map;

/**
 * Author: huoxingzhi
 * Date: 2020/12/16
 * Email: hxz_798561819@163.com
 */
public class PathVariableMethodArgumentResolver extends HandlerMethodArgumentResolverAdapter {

    @Override
    public boolean supportsParameter(Class<?> receiveClass,MethodParameter methodParameter) {
        PathVariable pathVariable = methodParameter.getParameter().getAnnotation(PathVariable.class);
        return !ObjectUtils.isEmpty(pathVariable);
    }

    @Override
    public Object resolveArgument(Message message, MethodParameter methodParameter) throws ConvertException {
        String httpURI = message.getHttpURI();
        String mappedURI = message.getMappedURI();
        if(!StringUtils.hasLength(httpURI) || !StringUtils.hasLength(mappedURI)){
            throw new ConvertException(getClass()+"arguement must mark a @PathVariable");
        }
        Map<String, String> uriTemplateVariables = PathMatchWrapper.extractUriTemplateVariables(mappedURI, httpURI);
        PathVariable pathVariable = methodParameter.getParameter().getAnnotation(PathVariable.class);
        String value = pathVariable.value();
        if(!StringUtils.hasLength(value)){
            value = methodParameter.getParameter().getName();
        }
        String paramKey = value;
        String paramValue = uriTemplateVariables.get(paramKey);
        return StringUtils.hasLength(paramValue)?paramValue:"";
    }


    @Override
    public Object resolveAndConvertArgument(Message message, MethodParameter methodParameter) {

        Object argument = resolveArgument(message, methodParameter);
        if(this.conversionService.canConvert(argument.getClass(),methodParameter.getParameter().getType())){
            return this.conversionService.convert(argument,methodParameter.getParameter().getType());
        }
        return argument;
    }
}
